﻿#region Using

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Commons.Diagnostics;
using SapFramework.Application;
using SapFramework.Queries;

#endregion

namespace SapFramework.Interface.Controls.Forms.Base
{
    /// <summary>
    /// Classe que guarda uma referencia aos formulários que foram abertos/carregados no SAP Business One.
    /// </summary>
    public class FormManager : Dictionary<string, Form>
    {
        /// <summary>
        /// Referencia para a classe à qual o FormManager pertence.
        /// </summary>
        public AddOn AddOn { get; private set; }

        /// <summary>
        /// Indexador para facilitar o acesso.
        /// </summary>
        /// <param name="aFormUniqueId">Código único do formulário, ou Form.UniqueID.</param>
        /// <returns>O formulário do PadaOne, quando encontrado. Retorna nulo, do contrário.</returns>
        public new Form this[ string aFormUniqueId ]
        {
            get { return ContainsKey( aFormUniqueId ) ? base[aFormUniqueId] : null; }
        }

        #region Construtores - Passados para internal para que não se possam criar instâncias desta classe fora desta DLL (em especial, da classe AddOn)

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that is empty, has the default initial capacity, and uses the default equality comparer for the key type.
        /// </summary>
        /// <param name="aAddOn">Referencia para a classe à qual o FormManager irá pertencer.</param>
        internal FormManager( AddOn aAddOn )
        {
            Contract.Requires.NotNull( () => aAddOn );
            AddOn = aAddOn;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that is empty, has the specified initial capacity, and uses the default equality comparer for the key type.
        /// </summary>
        /// <param name="aAddOn">Referencia para a classe à qual o FormManager irá pertencer.</param>
        /// <param name="capacity">The initial number of elements that the <see cref="T:System.Collections.Generic.Dictionary`2"/> can contain.</param><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0.</exception>
        internal FormManager( AddOn aAddOn, int capacity )
            : base( capacity )

        {
            Contract.Requires.NotNull( () => aAddOn );
            AddOn = aAddOn;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that is empty, has the default initial capacity, and uses the specified <see cref="T:System.Collections.Generic.IEqualityComparer`1"/>.
        /// </summary>
        /// <param name="aAddOn">Referencia para a classe à qual o FormManager irá pertencer.</param>
        /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> implementation to use when comparing keys, or null to use the default <see cref="T:System.Collections.Generic.EqualityComparer`1"/> for the type of the key.</param>
        internal FormManager( AddOn aAddOn, IEqualityComparer<string> comparer )
            : base( comparer )
        {
            Contract.Requires.NotNull( () => aAddOn );
            AddOn = aAddOn;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that is empty, has the specified initial capacity, and uses the specified <see cref="T:System.Collections.Generic.IEqualityComparer`1"/>.
        /// </summary>
        /// <param name="aAddOn">Referencia para a classe à qual o FormManager irá pertencer.</param>
        /// <param name="capacity">The initial number of elements that the <see cref="T:System.Collections.Generic.Dictionary`2"/> can contain.</param><param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> implementation to use when comparing keys, or null to use the default <see cref="T:System.Collections.Generic.EqualityComparer`1"/> for the type of the key.</param><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0.</exception>
        internal FormManager( AddOn aAddOn, int capacity, IEqualityComparer<string> comparer )
            : base( capacity, comparer )

        {
            Contract.Requires.NotNull( () => aAddOn );
            AddOn = aAddOn;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that contains elements copied from the specified <see cref="T:System.Collections.Generic.IDictionary`2"/> and uses the default equality comparer for the key type.
        /// </summary>
        /// <param name="aAddOn">Referencia para a classe à qual o FormManager irá pertencer.</param>
        /// <param name="dictionary">The <see cref="T:System.Collections.Generic.IDictionary`2"/> whose elements are copied to the new <see cref="T:System.Collections.Generic.Dictionary`2"/>.</param><exception cref="T:System.ArgumentNullException"><paramref name="dictionary"/> is null.</exception><exception cref="T:System.ArgumentException"><paramref name="dictionary"/> contains one or more duplicate keys.</exception>
        internal FormManager( AddOn aAddOn, IDictionary<string, Form> dictionary )
            : base( dictionary )

        {
            Contract.Requires.NotNull( () => aAddOn );
            AddOn = aAddOn;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class that contains elements copied from the specified <see cref="T:System.Collections.Generic.IDictionary`2"/> and uses the specified <see cref="T:System.Collections.Generic.IEqualityComparer`1"/>.
        /// </summary>
        /// <param name="aAddOn">Referencia para a classe à qual o FormManager irá pertencer.</param>
        /// <param name="dictionary">The <see cref="T:System.Collections.Generic.IDictionary`2"/> whose elements are copied to the new <see cref="T:System.Collections.Generic.Dictionary`2"/>.</param><param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> implementation to use when comparing keys, or null to use the default <see cref="T:System.Collections.Generic.EqualityComparer`1"/> for the type of the key.</param><exception cref="T:System.ArgumentNullException"><paramref name="dictionary"/> is null.</exception><exception cref="T:System.ArgumentException"><paramref name="dictionary"/> contains one or more duplicate keys.</exception>
        internal FormManager( AddOn aAddOn, IDictionary<string, Form> dictionary, IEqualityComparer<string> comparer )
            : base( dictionary, comparer )

        {
            Contract.Requires.NotNull( () => aAddOn );
            AddOn = aAddOn;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Collections.Generic.Dictionary`2"/> class with serialized data.
        /// </summary>
        /// <param name="aAddOn">Referencia para a classe à qual o FormManager irá pertencer.</param>
        /// <param name="info">A <see cref="T:System.Runtime.Serialization.SerializationInfo"/> object containing the information required to serialize the <see cref="T:System.Collections.Generic.Dictionary`2"/>.</param><param name="context">A <see cref="T:System.Runtime.Serialization.StreamingContext"/> structure containing the source and destination of the serialized stream associated with the <see cref="T:System.Collections.Generic.Dictionary`2"/>.</param>
        internal FormManager( AddOn aAddOn, SerializationInfo info, StreamingContext context )
            : base( info, context )
        {
            Contract.Requires.NotNull( () => aAddOn );
            AddOn = aAddOn;
        }

        #endregion

        /// <summary>
        /// Passa o método orinal para protegido, para que não seja usado explicitamente.
        /// </summary>
        /// <param name="aFormUniqueId">Id único do formulário no SAP Business One.</param>
        /// <param name="aForm">Referência para o formulário que será adicionado.</param>
        protected new void Add( string aFormUniqueId, Form aForm )
        {
            base.Add( aFormUniqueId, aForm );
        }

        /// <summary>
        /// Adiciona um novo formulário a coleção, baseado em seu tipo e código no SAP Business One.
        /// </summary>
        /// <remarks>
        /// Internamente ele chama o construtor da classe Form.
        /// </remarks>
        /// <param name="aFormUniqueId">Id único do formulário no SAP Business One.</param>
        /// <param name="aFormType">O tipo do formulário no SAP Business One.</param>
        public Form Add( string aFormUniqueId, string aFormType )
        {
            Type lFormClass = FormQueries.GetFormClassBySboFormType( aFormType );

            Form lNewForm = (Form) Activator.CreateInstance( lFormClass, new object[] {AddOn, aFormUniqueId} );

            base.Add( aFormUniqueId, lNewForm );

            return lNewForm;
        }

        /// <summary>
        /// Remove do controle de formulários o formulário de código especificado.
        /// </summary>
        /// <param name="aFormUniqueId">Id único do formulário no SAP Business One.</param>
        /// <returns>Verdadeiro quando conseguir remove-lo com sucesso</returns>
        public new bool Remove( string aFormUniqueId )
        {
            return base.Remove( aFormUniqueId );
        }

        /// <summary>
        /// Remove do controle de formulários o formulário especificado.
        /// </summary>
        /// <param name="aForm">Referência para o formulário que será removido.</param>
        /// <returns>Verdadeiro quando conseguir remove-lo com sucesso</returns>
        public bool Remove( Form aForm )
        {
            Contract.Requires.NotNull( () => aForm );

            return base.Remove( aForm.UniqueID );
        }
    }
}